package dto

import (
	"encoding/json"
	"time"
)

type MemberKYC struct {
	MemberID       int64
	Country        string
	Level          KYCLevel
	Type           KYCType
	ReviewResult   ReviewResult
	Applicant      *Applicant
	Documents      []*Document
	Limitation     Limitation
	LimitationInfo *LimitationInfo
	ExpireAt       time.Time
	UpdatedAt      time.Time
	CreateAt       time.Time
}

type Applicant struct {
	ID         string      `json:"id"` // unique id in provider
	Firstname  string      `json:"firstName"`
	Lastname   string      `json:"lastName"`
	Country    string      `json:"country"`    // country iso code
	Dob        string      `json:"dob"`        // date of birthday
	Gender     Gender      `json:"gender"`     // male, female
	Identities []*Identify `json:"identities"` // identities info, like id_card, passport, drivers
	PassTime   string      `json:"passTime"`   // level1通过时间，格式：2022-04-08T10:23:15.897Z
}

type Identify struct {
	Type       DocumentType `json:"type"`
	Country    string       `json:"country"`
	Firstname  string       `json:"firstName"`
	Lastname   string       `json:"lastName"`
	Validuntil string       `json:"validUntil"`
	Number     string       `json:"number"`
	Dob        string       `json:"dob"`
	RawType    string       `json:"raw_type"`
	IssuedDate string       `json:"issuedDate"`
}

func (m *MemberKYC) GetDocuments() string {
	b, _ := json.Marshal(m.Documents)
	return string(b)
}

func (m *MemberKYC) GetApplicant() string {
	b, _ := json.Marshal(m.Applicant)
	return string(b)
}

func (m *MemberKYC) UnmarshalApplicant(data string) *Applicant {
	a := new(Applicant)
	if err := json.Unmarshal([]byte(data), a); err != nil {
		return nil
	}

	m.Applicant = a
	return m.Applicant
}

func (m *MemberKYC) UnmarshalDocuments(data string) []*Document {
	docs := make([]*Document, 0)
	if err := json.Unmarshal([]byte(data), &docs); err != nil {
		return nil
	}

	m.Documents = docs
	return docs
}

func (m *MemberKYC) UnmarshalLimitation(data string) *LimitationInfo {
	l := new(LimitationInfo)
	if err := json.Unmarshal([]byte(data), l); err != nil {
		return nil
	}

	m.LimitationInfo = l
	return l
}

func (m *MemberKYC) GetMemberID() int64 {
	return m.MemberID
}

func (m *MemberKYC) GetCountry() string {
	return m.Country
}

func (m *MemberKYC) GetLevel() KYCLevel {
	return m.Level
}

func (m *MemberKYC) GetRealLevel() KYCLevel {
	if !m.ReviewResult.IsPassed() {
		if m.Level >= 1 {
			return m.Level - 1
		}
	}
	return m.Level
}

func (m *MemberKYC) GetType() int8 {
	return int8(m.Type)
}

func (m *MemberKYC) GetReviewResult() int8 {
	return int8(m.ReviewResult)
}

func (m *MemberKYC) GetLimitation() int8 {
	return int8(m.Limitation)
}

func (m *MemberKYC) ParseGender(gender string) Gender {
	switch gender {
	case "F", "f", "female", "Female":
		return GenderFemale
	case "M", "m", "male", "Male":
		return GenderMale
	default:
		return GenderUnknown
	}
}

func (m *MemberKYC) IsValid() bool {
	if m.Limitation != LimitationNone {
		return false
	}

	if m.ReviewResult != ReviewResultPass {
		return false
	}

	return true
}

func (m *MemberKYC) GetLimitationInfo() string {
	b, _ := json.Marshal(m.LimitationInfo)
	return string(b)
}

// GetIdentity get doc data according by document type
func (m *MemberKYC) GetIdentity(typ DocumentType) *Identify {
	if m.Applicant == nil {
		return nil
	}

	for _, doc := range m.Applicant.Identities {
		if doc.Type == typ {
			return doc
		}
	}

	return nil
}

type LimitationInfo struct {
	Level  KYCLevel  `json:"level"`  // 封禁目标等级
	Reason string    `json:"reason"` // 封禁原因，备注
	Type   BanType   `json:"type"`   // 封禁类型
	Start  time.Time `json:"start"`  // 限制开始时间
	End    time.Time `json:"end"`    // 限制结束时间
}

func (l *LimitationInfo) GetLevel() int8 {
	return int8(l.Level)
}

func (l *LimitationInfo) GetReason() string {
	return l.Reason
}

func (l *LimitationInfo) GetType() int {
	return int(l.Type)
}
